package com.yumo.kangchenjunga.customer;

import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.StringMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import com.yumo.kangchenjunga.activity.NoSuchActivityException;
import com.yumo.kangchenjunga.coupon.v1.CouponCustomerSummaryVo;
import com.yumo.kangchenjunga.coupon.v1.CouponService;
import com.yumo.kangchenjunga.coupon.v1.NoMoreAllocatedCouponException;
import com.yumo.kangchenjunga.coupon.v1.ObtainVo;
import com.yumo.kangchenjunga.log.LogEntity;
import com.yumo.kangchenjunga.log.LogService;
import com.yumo.kangchenjunga.security.CustomUserDetails;

@Service
public final class CustomerService {

	@Autowired
	private CustomerRepository repository;
	@Autowired
	private CouponService couponService;
	@Autowired
	private com.yumo.kangchenjunga.coupon.v2.CouponService couponServiceV2;
	@Autowired
	private LogService logService;

	public Customer create(Customer customer) {
		if (Objects.isNull(customer.customerLevel)) {
			throw new IllegalArgumentException("客户等级未选择");
		}
		return Customer.create(repository, customer);
	}

	public Customer queryById(int id) throws NoSuchCustomerException {
		return repository.findById(id).orElseThrow(NoSuchCustomerException::new);
	}

	public void delete(int id) {
		repository.deleteById(id);
	}

	public Customer modify(int id, Customer customer) throws NoSuchCustomerException {
		try {
			Customer row = repository.findById(id).orElseThrow();
			boolean logLevelChange = (0 != Integer.compare(row.customerLevel, customer.customerLevel));
			LogEntity log = null;

			if (logLevelChange) {
				log = genLog("等级变更", "成功",
						String.format("客户 [ 客户号: '%s' ] 等级从 %d 变更为 %d。", customer.customerNumber, row.customerLevel,
								customer.customerLevel));
			}

			var result = repository.save(customer);

			if (logLevelChange) {
				logService.log(log);
			}

			return result;
		} catch (NoSuchElementException e) {
			throw new NoSuchCustomerException();
		}
	}

	private LogEntity genLog(String op, String result, String detail) {
		var user = (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		var log = new LogEntity();

		log.op = op;
		log.opDetail = detail;
		log.opObject = "信托客户";
		log.opResult = result;
		log.opUserId = user.getId();
		log.opUsername = user.getUsername();

		return log;
	}

	public Iterable<Customer> list() {
		return repository.findAll();
	}

	public Iterable<Customer> listByCustomerLevels(Collection<Integer> customerLevels) {
		return repository.findByCustomerLevelIn(customerLevels);
	}

	public List<Customer> getCustomerByLevel(int level) {
		return repository.findByCustomerLevel(level);
	}

	public Page<Customer> page(Pageable pageable) {
		return repository.findAll(pageable);
	}

	public Page<CustomerVo> query(CustomerVo customer, Pageable pageable) {
		ExampleMatcher matcher = ExampleMatcher.matchingAll().withIgnorePaths("id").withIgnoreCase()
				.withStringMatcher(StringMatcher.CONTAINING);
		Example<Customer> example = Example.of(new Customer(customer), matcher);

		return repository.findAll(example, pageable).map(CustomerVo::new);
	}

	public List<Customer> getCustomeByIds(Collection<Integer> customerIds) {
		return repository.findByIdIn(customerIds);
	}

	public CouponCustomerSummaryVo getCouponSummary(int customerId) {
		return couponService.getCouponSummaryByCustomerId(customerId);
	}

	public ObtainVo obtain(int customerId, int activityId)
			throws NoMoreAllocatedCouponException, NoSuchActivityException {
		return couponServiceV2.obtain(customerId, activityId);
	}

}
